/*
 *   Copyright (C) 2009  Jens Kieselbach
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You may obtain a copy of the License at http://www.gnu.org/licenses/gpl.html
 */

package de.kieselbach.swing

import javax.swing.*
import com.jgoodies.looks.*
import com.jgoodies.looks.plastic.*

class UIResources {

    def resourceBundles = [:]
    def images = [:]

    def menubars = [:]
    def toolbars = [:]

    UIResources(def input) {

        def result = new XmlParser().parse(input)

        result.'resource-bundles'.'resource-bundle'.each() {elem ->
            def name = elem.'@name'
            def uri = elem.text()

            if (name != null && name.size() > 0 && uri != null && uri.size() > 0) {
                resourceBundles[name] = ResourceBundle.getBundle(uri)
            }
        }

        result.'images'.'image'.each() {elem ->
            def name = elem.'@name'
            def uri = elem.text()

            if (name != null && name.size() > 0 && uri != null && uri.size() > 0) {
                images[name] = new ImageIcon(getClass().getResource(uri))
            }
        }

        result.'menu-bar'.each() {elem ->
            def set = elem.'@set'
            if(set != null) {
                set = set.trim()
                if(set.length() <= 0) {
                    set = null
                }
            }
            if(set == null) {
                set = 'default'
            }

            if(menubars[set] != null) {
                throw new IllegalArgumentException('A menu bar in set \'' + set + '\' is already defined!')
            }
            
            menubars[set] = elem
        }

        result.'tool-bar'.each() {elem ->
            def set = elem.'@set'
            if(set != null) {
                set = set.trim()
                if(set.length() <= 0) {
                    set = null
                }
            }
            if(set == null) {
                set = 'default'
            }

            if(toolbars[set] != null) {
                throw new IllegalArgumentException('A tool bar in set \'' + set + '\' is already defined!')
            }

            toolbars[set] = elem
        }
    }

    void buildToolBar(def uiset, def elements) {

        elements.each {elem ->
            if (elem.name() == 'button') {
                addButton(uiset, elem)
            }
            else if (elem.name() == 'separator') {
                uiset.toolBar.addSeparator()
            }
            else if (elem.name() == 'glue') {
                uiset.toolBar.add(Box.createGlue())
            }
        }
    }

    void addButton(def uiset, def elem) {
        def bundle = elem.'@resource-bundle'
        def key = elem.'@resource-key'
        def tooltip = elem.'@tooltip-key'
        def image = elem.'@image'

        if ((bundle != null && bundle.size() > 0 && key != null && key.size() > 0) || (image != null && image.size() > 0)) {
            def button = new JButton()
            uiset.toolBar.add(button)

            if (bundle != null && bundle.size() > 0) {
                if(key != null && key.size() > 0) {
                    button.horizontalTextPosition = SwingConstants.CENTER
                    button.verticalTextPosition = SwingConstants.BOTTOM
                    button.font = button.font.deriveFont(9.0f)
                    button.text = resourceBundles[bundle].getString(key)
                }

                if(tooltip != null && tooltip.size() > 0) {
                    button.toolTipText = resourceBundles[bundle].getString(tooltip)
                }
            }

            if (image != null && image.size() > 0) {
                button.icon = images[image] as Icon
            }

            def command = elem.text()
            if (command != null && command.size() > 0) {
                button.actionCommand = command
                button.actionPerformed = uiset.doAction

                def resource = uiset.resources[command]
                if (resource == null) {
                    resource = new UIResource()
                    uiset.resources[command] = resource
                }

                resource.elements << button
            }
        }
    }

    void buildMenuBar(def uiset, def parent, def elements) {

        elements.each {elem ->
            if (elem.name() == 'menu') {
                addMenu(uiset, parent, elem)
            }
            else if (elem.name() == 'menu-item') {
                addMenuItem(uiset, parent, elem)
            }
            else if (elem.name() == 'separator') {
                addMenuSeparator(parent)
            }
        }
    }

    def initMenu(def menu, def text, def image) {
        def mnem = null
        def i = text.indexOf('\$')
        if (i >= 0 && (text.size() - 1) > i) {
            mnem = text.charAt(i + 1);
            text = text.substring(0, i) + text.substring(i + 1)
        }

        menu.text = text
        if (mnem != null) {
            menu.mnemonic = mnem
        }

        if (image != null && image.size() > 0) {
            menu.icon = images[image]
        }

        return menu
    }

    void addMenu(def uiset, def parent, def elem) {
        def bundle = elem.'@resource-bundle'
        def key = elem.'@resource-key'
        if (bundle != null && bundle.size() > 0 && key != null && key.size() > 0) {

            def text = resourceBundles[bundle].getString(key);
            def JMenu menu = new JMenu(text as String)

            parent.add(initMenu(menu, text, elem.'@image'))
            if (elem.'*'.size() > 0) {
                buildMenuBar(uiset, menu, elem.'*')
            }
        }
    }

    void addMenuItem(def uiset, def parent, def elem) {
        def bundle = elem.'@resource-bundle'
        def key = elem.'@resource-key'
        if (bundle != null && bundle.size() > 0 && key != null && key.size() > 0) {
            def text = resourceBundles[bundle].getString(key)
            def JMenuItem menuitem = new JMenuItem()
            parent.add(initMenu(menuitem, text, elem.'@image'))

            def accel = elem.'@accelerator'
            if (accel != null) {
                menuitem.accelerator = KeyStroke.getKeyStroke(accel)
            }

            def command = elem.text()
            if (command != null && command.size() > 0) {
                menuitem.actionCommand = command
                menuitem.actionPerformed = uiset.doAction

                def resource = uiset.resources[command]
                if (resource == null) {
                    resource = new UIResource()
                    uiset.resources[command] = resource
                }

                resource.elements << menuitem
            }
        }
    }

    void addMenuSeparator(def parent) {
        parent.add(new JSeparator())
    }

    // -------------------------------------------------------------

    UISet createUISet(def set) {

        if(set != null) {
            set = set.trim()
            if(set.length() <= 0) {
                set = null
            }
        }
        if(set == null) {
            set = 'default'
        }

        def uiset = new UISet()

        def menubar = menubars[set]
        if(menubar != null) {
            uiset.menuBar = new JMenuBar()
			
			uiset.menuBar.putClientProperty(Options.HEADER_STYLE_KEY, HeaderStyle.BOTH);
			uiset.menuBar.putClientProperty(PlasticLookAndFeel.BORDER_STYLE_KEY, BorderStyle.SEPARATOR);
			
            if (menubar.'*'.size() > 0) {
                buildMenuBar(uiset, uiset.menuBar, menubar.'*')
            }
        }

        def toolbar = toolbars[set]
        if(toolbar != null) {
            uiset.toolBar = new JToolBar()
			
			uiset.toolBar.putClientProperty(Options.HEADER_STYLE_KEY, HeaderStyle.BOTH);
			uiset.toolBar.putClientProperty(PlasticLookAndFeel.BORDER_STYLE_KEY, BorderStyle.SEPARATOR);
			uiset.toolBar.rollover = true
			uiset.toolBar.floatable = true
			
            if (toolbar.'*'.size() > 0) {
                buildToolBar(uiset, toolbar.'*')
            }
        }

        uiset
    }
}


